﻿// <copyright file="BlogController.cs" company="Clever Software">
// Copyright (c) 2013, 2014 All Right Reserved, http://www.cleversoftware.by
//
// This source is subject to the Microsoft Permissive License.
// Please see the License.txt file for more information.
// All other rights reserved.
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// </copyright>
// <author>Clever Software</author>
// <email>info@cleversoftware.by</email>
// <date>2014-02-04</date> 
// <summary>CleverCMS source code</summary>

namespace CleverCMS.Web.Cms.Admin.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Mvc;

    using Blog.Data.Entities;
    using Blog.Services;
    using Blog.Services.ViewModels;
    using CleverCMS.Core.Services;
    using CleverCMS.Core.Web.Filters;

    [Authorize(Roles = "Admin")]
    public class BlogController : Controller
    {
        private readonly BlogEntryService   m_blogService;
        private readonly LoggingService     m_loggingService;

        public BlogController(BlogEntryService  pageService, 
                              LoggingService    loggingService)
        {
            this.m_blogService = pageService;
            this.m_loggingService = loggingService;
        }

        public ViewResult List()
        {
            return View();
        }

        #region Categories
        
        /// <summary>
        /// Returns category view
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public ActionResult EditCategory(int? id)
        {
            BlogEntryCategoryEditModel model = new BlogEntryCategoryEditModel();
            if (id != null)
            {
                model.Category = m_blogService.GetCategoryById(id.Value);

                if (model.Category != null)
                    return View(model);
                else
                    TempData["SuccessResult"] = "Items was not found!";
            }
            return View(model);
        }

        /// <summary>
        /// Create/Update category
        /// </summary>
        /// <param name="cat"></param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Post)]
        [ValidateInput(false)]
        [CurrentUserFilter]
        public ActionResult EditCategory(BlogEntryCategoryEditModel cat, FormCollection forms)
        {
            ModelState.Remove("Category.Id");
            if (ModelState.IsValid)
            {
                if (cat.Category.Id > 0)
                {
                    BlogEntryCategory catFromDb = m_blogService.GetCategoryById(cat.Category.Id);
                    TryUpdateModel(catFromDb,"Category", forms.ToValueProvider());
                    m_blogService.UpdateCategory(catFromDb);
                }
                else
                    m_blogService.UpdateCategory(cat.Category);

                return Json(new { success = true, error = "" });
            }
            else
            {
                string errorString = "";
                foreach (var error in ModelState.Values.SelectMany(v => v.Errors))
                {
                    errorString += String.Concat(error.ErrorMessage, "; </BR>");
                }
                return Json(new { success = false, error = errorString });
            }
        }
        /// <summary>
        /// Delete category
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult DeleteCategory(int? Id)
        {
            if (!ModelState.IsValid)
                return Json(new { Result = "ERROR", Message = "", success = false, error = "Unknown error" });

            try
            {
                if (Id != null)
                    return m_blogService.DeleteCategory(Id.Value) ? Json(new { Result = "OK", success = true, error = "", Id = Id }) :
                                                            Json(new { Result = "ERROR", Message = "", success = false, error = "Unable to delete categry." });
                else
                    return Json(new { Result = "ERROR", Message = "", success = false, error = "Unknown error" });
            }
            catch (Exception exc)
            {
                return Json(new { Result = "ERROR", Message = exc.Message, success = false, error = exc.Message });
            }
        }

        #endregion

        #region Pages
        
        [HttpPost]
        public JsonResult ListPosts(int? id, int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = null)
        {
            try
            {
                int count = 0;
                var allPages = m_blogService.LoadPostsPaged(id, jtStartIndex, jtPageSize, jtSorting, out count)
                                            .Select(x => new {Id = x.Id, Header = x.Header, Visible = x.Visible, Created = x.Created})
                                            .ToList();

                return Json(new { Result = "OK", Records = allPages, TotalRecordCount = count });
            }
            catch (Exception ex)
            {
                return Json(new { Result = "ERROR", Message = ex.Message });
            }
        }
       
        /// <summary>
        /// Returns blog categories 
        /// </summary>
        /// <param name="jtStartIndex"></param>
        /// <param name="jtPageSize"></param>
        /// <param name="jtSorting"></param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult ListCategories(int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = null)
        {
            try
            {
                int categoriesCount = 0;
                var categories = m_blogService.LoadCategoriesPaged(jtStartIndex, jtPageSize, jtSorting, out categoriesCount)
                                              .Select(x => new {Id = x.Id, Picture = x.Picture, CategoryName = x.CategoryName})
                                              .ToList();
                return Json(new { Result = "OK", Records = categories, TotalRecordCount = categoriesCount });
            }
            catch (Exception ex)
            {
                return Json(new { Result = "ERROR", Message = ex.Message });
            }
        }
        
        /// <summary>
        /// Returns post view
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public ViewResult Edit(int? id)
        {
            if (id != null)
            {
                BlogEntry entry = m_blogService.GetById(id.Value);

                if (entry != null)
                {
                    return View(new AdminEditPostViewModel { Page = entry, Categories = GetCategories(entry.CategoryId), Visible = entry.Visible, ShowRating = entry.ShowRating});
                } 
                else
                    TempData["SuccessResult"] = "Items was not found!";
            }
            return View(new AdminEditPostViewModel { Page = new BlogEntry { Created = DateTime.Now, Visible= true }, Categories = GetCategories(null) });
        }
        
        /// <summary>
        /// Handle save post action
        /// </summary>
        /// <param name="vm"></param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Post)]
        [ValidateInput(false)]
        [CurrentUserFilter]
        public ActionResult Edit(AdminEditPostViewModel vm, FormCollection forms)
        {
            if (ModelState.IsValid)
            {
                var pageFromDb = m_blogService.GetById(vm.Page.Id);
                TryUpdateModel(pageFromDb, "Page", forms.ToValueProvider());
                pageFromDb.TagString = forms.GetValue("Tags");
                
                pageFromDb.Visible = vm.Visible;
                pageFromDb.ShowRating = vm.ShowRating;
                pageFromDb.CategoryId = vm.CategoryId;
                pageFromDb.Author = User.Identity.Name;

                m_blogService.Save(pageFromDb);
                m_loggingService.Info("Blog post saved.");
                return Json(new {success = true, error = ""});
            }
            else
            {
                string errorString = "";
                foreach (var error in ModelState.Values.SelectMany(v => v.Errors))
                {
                    errorString += String.Concat(error.ErrorMessage, "; </BR>");
                }
                return Json(new {success = false, error = errorString});
            }
        }

        /// <summary>
        /// Returns select list with or without preselected value
        /// </summary>
        /// <param name="selStatus"></param>
        /// <returns></returns>
        private SelectList GetCategories(int? selStatus)
        {
            IEnumerable<BlogEntryCategory> cats = m_blogService.LoadAllCategories();
            return new SelectList(cats, "Id", "CategoryName", selStatus);
        }
        
        /// <summary>
        /// Delete post
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult Delete(int? Id)
        {
            if (!ModelState.IsValid)
                return Json(new { Result = "ERROR", Message = "", success = false, error = "Unknown error" });

            try
            {
                if (Id != null)
                {
                    m_blogService.DeletePost(Id.Value);
                    m_loggingService.Warn("Blog post deleted.");
                    var v = new { Result = "OK", success = true, error = "", pageId = Id };
                    return Json(v);
                }
                else
                    return Json(new { Result = "ERROR", Message = "", success = false, error = "Unknown error" });
            }
            catch (Exception exc)
            {
                return Json(new { Result = "ERROR", Message = exc.Message, success = false, error = exc.Message });
            }
        }

        #endregion

        #region Tags

        [HttpPost]
        public JsonResult GetTags()
        {
            var tags = m_blogService.GetAllTags().ToList();
            return Json(tags.Select(x => new { x.Name }), JsonRequestBehavior.AllowGet);
        }

        #endregion
    }
}